package cn.huangsm.advance.ratelimiter.aop;

import com.alibaba.fastjson.JSON;
import com.google.common.util.concurrent.RateLimiter;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 自定义切面类解析注解
 *
 * @author huang
 * @PACKAGE_NAME cn.huangsm.advance.ratelimiter.aop
 * @PROJECT_NAME advance-code
 * @date 2019/1/19
 */
@Component
@Aspect
@Scope
@Slf4j
public class RateLimitAop {
    @Autowired
    private HttpServletResponse response;
    /**
     * 需要处理一个任务列表，但我们不希望每秒的任务提交超过五个
     */
    private RateLimiter rateLimiter = RateLimiter.create(5.0);

    @Pointcut("@annotation(cn.huangsm.advance.ratelimiter.RateLimitAspect)")
    public void rateLimiterPointCut() {
    }

    ;

    @Around("rateLimiterPointCut()")
    public Object around(ProceedingJoinPoint joinPoint) {
        /**
         * 得到令牌
         */
        Boolean flag = rateLimiter.tryAcquire();
        Object obj = null;
        try {
            if (flag) {
                obj = joinPoint.proceed();
                log.info("得到令牌!");
            } else {
                String result = JSON.toJSONString("抱歉，操作过于频繁，请稍等片刻在操作！");
                log.info("未获得令牌!");
                output(response, result);
            }
        } catch (Throwable e) {
            e.printStackTrace();
        }
        System.out.println("是否得到令牌=" + flag + ",参数=" + obj);
        return obj;
    }

    public void output(HttpServletResponse response, String msg) throws IOException {
        response.setContentType("application/json;charset=UTF-8");
        ServletOutputStream outputStream = null;
        try {
            outputStream = response.getOutputStream();
            outputStream.write(msg.getBytes("UTF-8"));
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            outputStream.flush();
            outputStream.close();
        }
    }
}
